Skip to content

Batched RHS via Krylov.jl block methods (GMRES/MINRES)#1074

Merged
ChrisRackauckas merged 2 commits into
SciML:mainfrom
ChrisRackauckas-Claude:block-krylov-batched
Jul 5, 2026
Merged

Batched RHS via Krylov.jl block methods (GMRES/MINRES)#1074
ChrisRackauckas merged 2 commits into
SciML:mainfrom
ChrisRackauckas-Claude:block-krylov-batched

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Please ignore until reviewed by @ChrisRackauckas. Draft; opened by an agent.

Follow-up to #1072, answering the review question "Krylov.jl does not support batched solves?" — it does, for a subset: block_gmres and block_minres.

  • KrylovJL_GMRES / KrylovJL_MINRES with a matrix b now build BlockGmresWorkspace / BlockMinresWorkspace and solve natively through krylov_solve! (M/N preconditioners, restart, tolerances all pass through; solution read from .X).
  • The other Krylov methods (no block variants) keep the informative ArgumentError, with the message updated to point at the block-capable options.
  • The DefaultLinearSolver operator-path GMRES choice is un-gated, so solve(LinearProblem(op, B)) with a matrix-free operator and matrix B works out of the box.

Verified locally (Julia 1.12): block GMRES ≈ A\B (Success, right shape) for dense and via FunctionOperator default; block MINRES on symmetric; cache reuse with swapped B; KrylovJL_CG still errors informatively.

Also observed while integrating downstream (ExponentialUtilities#236): dense LUFactorization refactorization always copies A (fact = lu(A, check = false) in the non-sparse branch of its solve!), making cache reuse O(n²)-allocating; GenericLUFactorization is the allocation-free option today. An opt-in in-place dense refactorization (honoring alias_A) would let LAPACK-speed LU be allocation-free too — happy to add it here or separately.

🤖 Generated with Claude Code

Krylov.jl provides block_gmres and block_minres, so those KrylovJL
variants now accept matrix right-hand sides natively via
BlockGmresWorkspace/BlockMinresWorkspace instead of erroring; the
remaining Krylov methods (no block variants) keep the informative
ArgumentError. The DefaultLinearSolver operator path's GMRES choice is
un-gated accordingly, so `solve(LinearProblem(op, B))` with an operator A
and matrix B now works out of the box.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The resolved LinearAliasSpecifier.alias_A from init is now stored on the
LinearCache. When the user permitted overwriting A, the dense
LUFactorization refactorization path (after cache.A = X) runs
lu!(cache.A) in place instead of paying lu's O(n^2) copy on every
refactorization.

Also updates the stale batch testset that still expected KrylovJL_GMRES
to reject matrix right-hand sides: block GMRES/MINRES support made that
path solve instead of throw, so it now asserts correct batched solutions
and keeps the informative-error checks on the methods without block
variants.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review July 5, 2026 09:05
@ChrisRackauckas ChrisRackauckas merged commit bebec0d into SciML:main Jul 5, 2026
58 of 59 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants